package net.neptech.service.impl;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.neptech.dto.sys.DeptStaffVo;
import net.neptech.exception.BusinessException;
import net.neptech.feign.SystemFeignClient;
import net.neptech.model.appointment.ClnicStaff;
import net.neptech.model.vo.ClnicStaffVo;
import net.neptech.model.vo.StaffDetailVo;
import net.neptech.repository.ClnicStaffRepository;
import net.neptech.service.IClnicStaffService;
import net.neptech.utils.BeanCopyUtils;
import net.neptech.utils.DateUtils;
import net.neptech.vm.ResponseResult;
import net.neptech.vm.enums.ResultStatusEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class IClnicStaffServiceImpl implements IClnicStaffService {
    @Autowired
    ClnicStaffRepository clnicStaffRepository;
    @Resource(name ="redisTemplate")
    RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    public SystemFeignClient feignClient;

    @Override
    public ResponseResult<List<ClnicStaff>> getClinicStaffList() {
        return null;
    }
    /**
     * 查询最近一周某医生的号源信息
     * @param staffId
     * @return
     */
    @Override
    public ResponseResult<List<ClnicStaffVo>> getClinicStaffListByWeek(String staffId,Integer typeId) {
        Date today = DateUtils.getStartTime(new Date());
        Date sevenDaysLater = DateUtils.getFutureDate(today, 7);
        List<ClnicStaffVo> clnicStaffVos = new ArrayList<>();
        log.info("curretnDate:{},sevenDaylater{}",today,sevenDaysLater);
       try{
           List<ClnicStaff> clnicStaffList =
                   clnicStaffRepository.findDoctorAvailability(typeId,Long.valueOf(staffId),
                           today, sevenDaysLater);

          clnicStaffVos = BeanCopyUtils.copyBeanList(clnicStaffList, ClnicStaffVo.class);
           log.info("查询最近一周某医生的号源信息，staffId：{}",  clnicStaffList);
        }catch (Exception e){

            log.error("查询最近一周某医生的号源信息失败，staffId：{}",e.getMessage());
            throw  new BusinessException(ResultStatusEnum.INTERNAL_SERVER_ERROR);
        }
       // 返回信息
        return ResponseResult.success(clnicStaffVos);
    }

    /**
     * 号池增加测试用
     */

    /**
     * 修改号库存
     */
    @Override
    public Integer updateClinicStaffSlotById(Long id, Integer num) {
        Integer result = clnicStaffRepository.updateSlotById(id, num);
        if (result != 1) {
            log.error("修改号库存失败，id：{}",id);
            throw  new BusinessException(ResultStatusEnum.INTERNAL_SERVER_ERROR);
        }
        return result;
    }
    /**
     * 根据日期查询该科室坐诊医生详细信息
     * @param
     * @param date 日期
     * @param deptId 科室id
     * @param typeId 0.排班预约线下/1.排班预约线上
     * @return
     */

    @Override
    public ResponseResult<List<ClnicStaffVo>> getClinicStaffListByDate(Date date,
                                                                     Long deptId,
                                                                     Byte typeId
    ) {
        List<ClnicStaffVo> clnicStaffVos = null;
        try {
        // 开始时间
        Date startDate = DateUtils.target(date, 0, 0, 0, 0);
        // 结束时间
        Date endDate = DateUtils.target(date, 23, 59, 59, 999);
        List<ClnicStaff> clnicStaffList = clnicStaffRepository.
                findClinicStaffByDateAndDeptId(startDate, endDate, deptId,typeId);
        log.info("根据日期查询该科室坐诊医生详细信息，date：{}，deptId：{}，typeId：{}",date,deptId,typeId);
        //映射到vo
        if (clnicStaffList != null && clnicStaffList.size() > 0) {
         clnicStaffVos = BeanCopyUtils.copyBeanList(clnicStaffList, ClnicStaffVo.class);
        //取ids
        List<Long> staffIds = clnicStaffList.stream()
                .map(ClnicStaff::getStaffId)
                .collect(Collectors.toList());
        //取医生详细信息
        Map<Long, StaffDetailVo> deptStaffVoMap = getDeptStaffVoMap(staffIds);
        //  加到vo
        clnicStaffVos.forEach(clnicStaffVo -> {
            StaffDetailVo staffDetailVo = deptStaffVoMap.get(clnicStaffVo.getStaffId());
            clnicStaffVo.setStaffDetailVo(staffDetailVo);
        });
        }
        }catch (Exception e){
            log.error("根据日期查询该科室坐诊医生详细信息失败，date：{}，deptId：{}，typeId：{}",date,deptId,typeId);
           e.printStackTrace();
            throw  new BusinessException(ResultStatusEnum.INTERNAL_SERVER_ERROR);
        }

        return ResponseResult.success(clnicStaffVos);
    }

    /**
     * 批量查询员工基本信息
     *
     * @param staffIds
     * @return
     */
    @Override
    public Map<Long, StaffDetailVo> getDeptStaffVoMap(List<Long> staffIds){
        // 1 2 3 4 5 6  7 8 9 10
        ResponseResult<List<DeptStaffVo>> staffItems = feignClient.getByStaffIds(staffIds);
        List<DeptStaffVo> data = staffItems.getData();

        Map<Long, StaffDetailVo> staffDetailVoMap = new HashMap<>();
        data.forEach(datum -> {
            StaffDetailVo staffDetailVo = BeanCopyUtils.copyBean(datum, StaffDetailVo.class);
            staffDetailVoMap.put(datum.getStaffId(),staffDetailVo);
        });
        return staffDetailVoMap;
    }




    /**
     * 号池增加测试用
     */
    @Override
    public ResponseResult<Boolean>  putRedis(Integer dayNum) {
        // 先从数据库里查数据
        //获取当天后n天的坐诊医生号源信息
        Date today = new Date();
        Date sevenDaysLater = DateUtils.getFutureDate(today, dayNum);
        //近n天排班信息
        List<ClnicStaff> clnicStaffList = clnicStaffRepository
                .findDoctorAvailabilityByWeek(today,sevenDaysLater);
        //放号
        log.info("clnicStaffList:{}",clnicStaffList);
        clnicStaffList.forEach(clnicStaff -> {
            Integer slotTotal = clnicStaff.getSlotTotal();
            Long staffId = clnicStaff.getStaffId();
            Long clnicId = clnicStaff.getId();
            String keySiff = clnicStaff.getTypeId() == 1 ? "xxyy:" : "xsyy:";
            String key = keySiff+"doctor:"+staffId+":clnicId:"+clnicId;
            if (slotTotal > 0 && !redisTemplate.hasKey(key) ) {
                for (int i = 1; i < slotTotal+1; i++) {
                    redisTemplate.opsForList().
                            rightPush(key,i);
                }
            }
            log.info("初始化号池，staffId：{}，clnicId：{}，slotTotal：{}",staffId,clnicId,slotTotal);
            //过期时间设置
            //根据date 获取当前天的时间戳
            Date tTieme = DateUtils.target(clnicStaff.getClnicTime(),23,0,0,0);
            //在某天删除该键   过期时间
            redisTemplate.expireAt(key,tTieme);
        });
        //筛选出号源在7天内的
        return ResponseResult.success(true);
    }

    /**
     * 增加号池  与定时任务排班连用
     */
    @Override
    public boolean putSlot(ClnicStaff clnicStaff) {
        //放号
        Integer slotTotal = clnicStaff.getSlotTotal();
        Long staffId = clnicStaff.getStaffId();
        Long clnicId = clnicStaff.getId();
        StringBuilder key = new StringBuilder();
        String keySiff = clnicStaff.getTypeId() == 1 ? "xxyy:" : "xsyy:";
        key.append(keySiff)
                .append("doctor:")
               .append(staffId)
                .append(":clnicId:")
                .append(clnicId);

        log.info(key.toString());
        if (slotTotal > 0 && !redisTemplate.hasKey(key.toString()) ) {
            for (int i = 1; i < slotTotal+1; i++) {
                redisTemplate.opsForList().
                        rightPush(key.toString(),i);
            }
        }
        log.info("初始化号池，staffId：{}，clnicId：{}，slotTotal：{}",staffId,clnicId,slotTotal);
            //过期时间设置
            //根据date 获取当前天的时间戳
        Date tTieme = DateUtils.target(clnicStaff.getClnicTime(),23,0,0,0);
            //在某天删除该键   过期时间
        redisTemplate.expireAt(key.toString(),tTieme);

        //筛选出号源在7天内的
        return true;
    }

    @Override
    public List<ClnicStaffVo> getClnicStaff(Long staffId) {
        //获取当前日期
        Date startDay = DateUtils.target(new Date(),0,0,0,0);
        Date endDay = DateUtils.target(new Date(),22,59,59,99);
        List<ClnicStaff> clnicStaffs = clnicStaffRepository.
                findClnicStaffsByClnicTime(staffId, startDay, endDay);
        return BeanCopyUtils.copyBeanList(clnicStaffs, ClnicStaffVo.class);
    }


}
